package BlockR.util;

import java.util.Arrays;

public class Byte_SHIFT {   //循环移位

    public static void main(String[] arg) { //测试
        byte[] test = new byte[128];
        test[0] = 0;
        for (int i = 1; i < 128; i++) {
            test[i] = 1;
        }
        System.out.println(Arrays.toString(test));
        test = leftShift(test, 250,128);
        System.out.println(Arrays.toString(test));
    }

    public static byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static int toByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    private static void RotateRightOne(byte[] bytes) {
        byte valBit;
        valBit = (byte) (bytes[bytes.length - 1] << (byte) (7));
        for (int i = bytes.length - 1; i > 0; i--) {
            bytes[i] = (byte) ((bytes[i] >> (byte) (1)) | (bytes[i - 1] << (byte) (7)));
        }
        bytes[0] = (byte) ((bytes[0] >> (byte) (1)) | valBit);
    }

    public static byte[] rightShift(byte[] bytes, int X,int arraySize) {  //X<bytes.length
        int byte_move;
        int binary_move;
        if (X % (arraySize*8) == 0) {
            return bytes;
        } else {
            if (X > arraySize*8) {
                while (X > arraySize*8) {
                    X -= arraySize*8;
                }
            }
            byte_move = (X - X % 8) / 8;
            byte[] new_bytes = new byte[arraySize];
            System.arraycopy(bytes, 0, new_bytes, byte_move, bytes.length - byte_move);
            System.arraycopy(bytes, bytes.length - byte_move, new_bytes, 0, byte_move);
            binary_move = X % 8;
            if (binary_move == 0) {
                return new_bytes;
            } else {
                cyclic_right_shift(new_bytes, binary_move);
                return new_bytes;
            }
        }
    }

    public static byte[] leftShift(byte[] bytes, int X,int arraySize) {  //X<bytes.length
        int byte_move;
        int binary_move;
        if (X % (arraySize*8) == 0) {
            return bytes;
        } else {
            if (X > arraySize*8) {
                while (X > arraySize*8) {
                    X -= arraySize*8;
                }
            }
            byte_move = (X - X % 8) / 8;
            byte[] new_bytes = new byte[arraySize];
            System.arraycopy(bytes, byte_move, new_bytes, 0, bytes.length - byte_move);
            System.arraycopy(bytes, 0, new_bytes, bytes.length - byte_move, byte_move);
            binary_move = X % 8;
            if (binary_move == 0) {
                return new_bytes;
            } else {
                cyclic_left_shift(new_bytes, binary_move);
                return new_bytes;
            }
        }
    }

    private static void cyclic_left_shift(byte[] bytes, int X) {
/*        byte first_byte_begin_bit = (byte) (bytes[0] >> (byte) (8 - X));
        if (first_byte_begin_bit < 0) {
            byte temp = (byte) ((byte) (-128) >> (byte) (8 - X - 1));
            first_byte_begin_bit = (byte) (first_byte_begin_bit ^ temp);
        }
        for (int file_num = 0; file_num < bytes.length - 1; file_num++) {
            byte A = (byte) (bytes[file_num] << (byte) (X));
            byte B = (byte) (bytes[file_num + 1] >> (byte) (8 - X));
            if (B < 0) {
                byte temp = (byte) ((byte) (-128) >> (byte) (8 - X - 1));
                B = (byte) (B ^ temp);
            }
            bytes[file_num] = (byte) (A | B);
        }
        byte A = (byte) (bytes[bytes.length - 1] << (byte) (X));
        bytes[bytes.length - 1] = (byte) (A | first_byte_begin_bit);*/
        int first_byte_begin_bit =  bytes[0] >>> 8 - X;
        for (int i = 0; i <bytes.length-1; i++)
        {
            int A=(bytes[i]&0xff)<<  X;
            int B=bytes[i + 1] >>> (8 - X);
            bytes[i] = (byte) (A|B);
        }
        bytes[bytes.length-1]=(byte)((bytes[bytes.length-1]&0xff)<<X);
        bytes[bytes.length-1] = (byte)(bytes[bytes.length-1]|first_byte_begin_bit);
    }

    private static void cyclic_right_shift(byte[] bytes, int X) {
/*        byte end_byte_final_bit = (byte) (bytes[bytes.length - 1] << (byte) (8 - X));
        for (int file_num = bytes.length - 1; file_num > 0; file_num--) {
            byte A = (byte) (bytes[file_num] >> (byte) (X));
            byte B = (byte) (bytes[file_num - 1] << (byte) (8 - X));
            if (A < 0) {
                byte temp = (byte) ((byte) (-128) >> (byte) (X - 1));
                A = (byte) (A ^ temp);
            }
            bytes[file_num] = (byte) (A | B);
//            bytes[file_num] = (byte) ((byte) ((bytes[file_num] >> (byte) (X))) | (byte) ((bytes[file_num - 1] << (byte) (8 - X))));
        }
        byte A = (byte) (bytes[0] >> (byte) (X));
        if (A < 0) {
            byte temp = (byte) ((byte) (-128) >> (byte) (X - 1));
            A = (byte) (A ^ temp);
        }
        bytes[0] = (byte) (A | end_byte_final_bit);*/
        //bytes[0] = (byte) ((byte) ((bytes[0] >> (byte) (X))) | end_byte_final_bit);
        int end_byte_end_bit =  bytes[bytes.length - 1] << 8 - X;
        for (int i = bytes.length - 1; i > 0; i--)
        {
            int A=(bytes[i]&0xff)>>>  X;
            int B=bytes[i - 1] << 8 - X;
            bytes[i] = (byte) (A|B);
        }
        bytes[0]=(byte)((bytes[0]&0xff)>>>X);
        bytes[0] = (byte)(bytes[0]|end_byte_end_bit);
    }
}
